import TipPanel from "../UI/TipPanel";
import Cell from "./Cell";
import GamePlayPanel from "../UI/GamePlayPanel";
import GameManager, { GameState } from "../Manager/GameManager";
import AudioManager from "../Manager/AudioManager";

const {ccclass, property} = cc._decorator;

@ccclass
export default class CellFunctions {
    public static CreateGrid(x:number, y:number, cellSize:number)
    {
        let node = cc.instantiate(GameManager.Instance.Prefab_Grid);
        node.parent = GameManager.Instance.Node_2D;
        node.setPosition(0, 0);
        node.width = cellSize;
        node.height = cellSize;

        var pos_x = cellSize * x - GameManager.Instance.width / 2  + cellSize / 2;
        var pos_y = cellSize * y - GameManager.Instance.height_screen / 2 + cellSize / 2 + GameManager.Instance.padding_bottom;
        node.setPosition(pos_x, pos_y);
        
        return node;
    }

    public static CreateCell(id:number, x:number, y:number, cellList:Array<Array<Cell>>)
    {
        let node = cc.instantiate(GameManager.Instance.Prefab_Cell);
        let cell:Cell = node.getComponent(Cell);
        cell.isNew = true;
        if (cellList != null)
        {
            cellList[x][y] = cell;
            cell.Init(id, x, y);
        }
        
        cell.RefreshUI();
        
        return cell;
    }

    //生成最上面一行元素
    //目前采用一种保底机制，保证每种元素至少随机出一个
    public static CreateTopLine(row:number = 0)
    {
        GameManager.Instance.timer = 0;

        let y:number = row - 1;
        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            let id:number = Math.floor(Math.random() * (GameManager.Instance.type_count - 1)) + 1;
            let cell:Cell = CellFunctions.CreateCell(id, x, y, GameManager.Instance.cellList);
        }

        //目前采用一种保底机制，保证每种元素至少随机出一个
        // 炸弹10次出现一次，且一次出现一个
        let count:number = GameManager.Instance.type_count - 1
        let ran:number = Math.random();
        if(ran <= 0.3)
        {
            count = GameManager.Instance.type_count; //出现炸弹
        }
        else
        {
            count = GameManager.Instance.type_count - 1;
        }

        let items:Array<number> = CellFunctions.GetRandomArray(count, 0, GameManager.Instance.col - 1);
        for (let i = 0; i < items.length; i++)
        {
            let x:number = items[i];
            let cell:Cell = GameManager.Instance.cellList[x][y];
            cell.id = i + 1;
            cell.RefreshUI();
        }        
    }

    // 获取当前操作的一行
    public static GetCurrentMovingRow():number
    {
        let row:number = 0;
        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            for (let y = GameManager.Instance.row - 1 + 1; y >= 0; y--)
            {
                let cell:Cell = GameManager.Instance.cellList[x][y];
                if (cell != null)
                {
                    row = y + 1;
                    return row;
                }
            }
        }

        return row;
    }

    // 左右移动
    public static MoveLefOrRight(dir:number)
    {
        if (GameManager.Instance.gameState != GameState.Free)
        {
            return;
        }
        
        AudioManager.Instance.audio_move.play();
        // AudioManager.Instance.Play(AudioManager.Instance.audio_move);

        let topIdList:Array<Cell>  = new Array<Cell>();
        let copyIdList:Array<number> = new Array<number>();
        
        let y = CellFunctions.GetCurrentMovingRow() - 1;
        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            let cell:Cell = GameManager.Instance.cellList[x][y];
            topIdList[x] = cell;
            copyIdList[x] = cell.id;
        }

        for (let x = 0; x <= topIdList.length - 1; x++)
        {
            let cell:Cell = topIdList[x];
            let nextIndex:number = x;
            if (dir == -1)
            {
                nextIndex = x + 1;
                if (nextIndex > topIdList.length - 1)
                {
                    nextIndex = 0;
                }
            }
            else if (dir == 1)
            {
                nextIndex = x - 1;
                if (nextIndex < 0)
                {
                    nextIndex = topIdList.length - 1;
                }
            }
            
            cell.id = copyIdList[nextIndex];
            cell.RefreshUI();
        }
    }

    //通过x和y获得一个指定Cell
    public static GetCell(x:number, y:number):Cell
    {
        let cell:Cell = null;

        if (x >= 0 && x <= GameManager.Instance.col - 1 &&
            y >= 0 && y <= GameManager.Instance.row - 1)
        {
            cell = GameManager.Instance.cellList[x][y];
        }

        return cell;
    }

    public static Check(cell:Cell, list:Array<Cell>):Array<Cell>
    {
        if (list == null)
        {
            list = new Array<Cell>();
        }

        if (cell == null)
        {
            return null;
        }

        if (list.indexOf(cell) != -1)
        {
            return list;
        }
        else
        {
            list.push(cell);
        }

        let x:number = cell.x;
        let y:number = cell.y;
        let cell_up:Cell = CellFunctions.GetCell(x, y + 1);
        let cell_down:Cell = CellFunctions.GetCell(x, y - 1);
        let cell_left:Cell = CellFunctions.GetCell(x - 1, y);
        let cell_right:Cell = CellFunctions.GetCell(x + 1, y);

        if (cell_up != null && cell.id == cell_up.id)
        {
            CellFunctions.Check(cell_up, list);
        }
        if (cell_down != null && cell.id == cell_down.id)
        {
            CellFunctions.Check(cell_down, list);
        }
        if (cell_left != null && cell.id == cell_left.id)
        {
            CellFunctions.Check(cell_left, list);
        }
        if (cell_right != null && cell.id == cell_right.id)
        {
            CellFunctions.Check(cell_right, list);
        }
        
        return list;
    }

    //检测所有相邻并有相同id元素的Cell，组成列表
    public static GetAllSameList():Array<Array<Cell>>
    {
        let lists:Array<Array<Cell>> = new Array<Array<Cell>>();

        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            for (let y = 0; y <= GameManager.Instance.row - 1; y++)
            {
                let cell:Cell = GameManager.Instance.cellList[x][y];
                let isContains:boolean = false;
                lists.forEach(function (list) {
                    if (list != null && list.indexOf(cell) != -1)
                    {
                        isContains = true;
                    }
                });

                if (isContains == false)
                {
                    let sameList:Array<Cell> = CellFunctions.Check(cell, null);
                    lists.push(sameList);
                }
            }
        }

        return lists;
    }

    //三消
    public static KillAllSameList():boolean
    {
        GameManager.Instance.isKill = false;
        let lists:Array<Array<Cell>> = CellFunctions.GetAllSameList();
        if (lists != null)
        {
            lists.forEach(function (list)
            {
                if (list != null)
                {
                    if (list.length >= 3)
                    {
                        GameManager.Instance.isKill = true;
                        GameManager.Instance.killCellList.push(list);
                    }
                }
            });
        }

        if (GameManager.Instance.isKill) {
            CellFunctions.DelayFunction(
            ()=>{
                let list = GameManager.Instance.killCellList[0];
                let removed = GameManager.Instance.killCellList.splice(0, 1);

                GameManager.Instance.score += list.length;
                GamePlayPanel.Instance.RefreshScore(GameManager.Instance.score);
                AudioManager.Instance.audio_disappear.play();
                let item_cell:Cell = list[0];
                list.forEach(function (item_cell)
                {
                    if (list != null && list.indexOf(item_cell) != -1)
                    {
                        item_cell.Dead();
                    }
                });
            },
            ()=>{
                GameManager.Instance.scheduleOnce(function(){
                    GameManager.Instance.ChangeStateMachine(GameState.Bomb);
                }, 0.5);
            }, GameManager.Instance.killCellList.length, 0.5);
        }
        else
        {
            GameManager.Instance.ChangeStateMachine(GameState.Bomb);
        }

        return GameManager.Instance.isKill;
    }

    //操作并所有下移
    public static Bomb():boolean
    {
        let isBomb:boolean = false;
        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            for (let y = 0; y <= GameManager.Instance.row - 1; y++)
            {
                let cell:Cell = GameManager.Instance.cellList[x][y];
                if (cell != null && cell.id == 6)
                {
                    GameManager.Instance.isKill = true;
                    isBomb = true;
                    CellFunctions.Explore9(cell.x, cell.y);
                }
            }
        }

        if (isBomb)
        {
            GameManager.Instance.scheduleOnce(function(){
                GameManager.Instance.ChangeStateMachine(GameState.Fall);
            }, 0.4);
        }
        else
        {
            // GameManager.Instance.RoundEnd();
            GameManager.Instance.ChangeStateMachine(GameState.Fall);
        }

        return GameManager.Instance.isKill;
    }

    //操作并所有下移
    public static ControlMoveDown()
    {
        if (GameManager.Instance.gameState == GameState.Free)
        {
            GameManager.Instance.ChangeStateMachine(GameState.Fall);
        }
    }

    //所有下移
    public static MoveDownAllCell():boolean
    {
        let isMove:boolean = false;
        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            for (let y = 0; y <= GameManager.Instance.row - 1 + 1; y++)
            {
                let oneMove:boolean = CellFunctions.MoveDownCell(x, y);
                if (oneMove == true)
                {
                    isMove = true;
                }
            }
        }

        if (isMove == true)
        {
            AudioManager.Instance.audio_fall.play();
        }
        else
        {
            GameManager.Instance.RoundEnd();
        }

        return isMove;
    }

    //下移到不能下移的位置
    public static MoveDownCell(x:number, y:number):boolean
    {
        // TipPanel.Instance.Open("MoveDownCell");
        let isMove:boolean = false;

        let cell:Cell = GameManager.Instance.cellList[x][y];
        if (cell != null)
        {
            let firstEmptyCell_Y:number = CellFunctions.GetFirstEmptyCellY(x);
            if (firstEmptyCell_Y >= 0 && cell.y > firstEmptyCell_Y)
            {
                isMove = true;

                GameManager.Instance.movingCellList.push(cell);

                let y = cell.y;
                cell.Set(x, firstEmptyCell_Y);
                
                let pos:cc.Vec2 =  CellFunctions.GetPosition(cell.x, firstEmptyCell_Y);
                
                cc.tween(cell.node)
                .to(0.08 * (y - firstEmptyCell_Y), { y: pos.y })
                .call(() => {
                    let index = GameManager.Instance.movingCellList.indexOf(cell);
                    if(index != -1)
                    {
                        let removed = GameManager.Instance.movingCellList.splice(index, 1);
                    }
                    if(GameManager.Instance.movingCellList.length <= 0)
                    {
                        GameManager.Instance.scheduleOnce(function(){
                            // TipPanel.Instance.Open("KillAllSameList");
                            // CellFunctions.KillAllSameList();
                            GameManager.Instance.ChangeStateMachine(GameState.Match);
                        }, 0.2);
                    }
                })
                .start()
            }
        }

        return isMove;
    }
    
    //获取从下到上一列中第一个为空的Cell
    public static GetFirstEmptyCellY(x:number):number
    {
        let firstEmptyCell_Y:number = -1;

        for (let y = 0; y <= GameManager.Instance.row - 1; y++)
        {
            let item_cell:Cell = GameManager.Instance.cellList[x][y];
            if (item_cell == null)
            {
                firstEmptyCell_Y = y;
                break;
            }
        }

        return firstEmptyCell_Y;
    }

    //清除所有
    public static ClearAll()
    {
        if (GameManager.Instance.cellList == null || GameManager.Instance.cellList.length == 0)
        {
            return;
        }

        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            for (let y = 0; y <= GameManager.Instance.row - 1 + GameManager.Instance.add_row; y++)
            {
                let cell:Cell = GameManager.Instance.cellList[x][y];
                if (cell != null)
                {
                    cell.Dead();
                }
            }
        }
    }

    //刷新所有
    public static RefreshAll()
    {
        if (GameManager.Instance.cellList == null || GameManager.Instance.cellList.length == 0)
        {
            return;
        }

        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            for (let y = 0; y <= GameManager.Instance.row - 1 + GameManager.Instance.add_row; y++)
            {
                let cell:Cell = GameManager.Instance.cellList[x][y];
                if (cell != null)
                {
                    cell.RefreshPos();
                    cell.RefreshUI();
                }
            }
        }
    }

    //刷新所有
    public static SetAllNotNew()
    {
        if (GameManager.Instance.cellList == null || GameManager.Instance.cellList.length == 0)
        {
            return;
        }

        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            for (let y = 0; y <= GameManager.Instance.row - 1; y++)
            {
                let cell:Cell = GameManager.Instance.cellList[x][y];
                if (cell != null)
                {
                    cell.isNew = false;
                }
            }
        }
    }

    // 从minNum到maxNum取其中Number个
    // Number随机数个数
    // minNum随机数下限
    // maxNum随机数上限
    public static GetRandomArray(Number:number, minNum:number, maxNum:number):Array<number>
    {
        let j:number;
        let b:Array<number> = new Array<number>();
        for (let j = 0; j < Number; j++)
        {
            // UnityEngine.Random.Range(minNum, maxNum + 1);
            let i:number = Math.floor(Math.random() * maxNum) + minNum;
            let num:number = 0;
            for (let k = 0; k < j; k++)
            {
                if (b[k] == i)
                {
                    num = num + 1;
                }
            }
            if (num == 0)
            {
                b[j] = i;
            }
            else
            {
                j = j - 1;
            }
        }
        return b;
    }

    // 获取最高的y值
    public static GetMaxY():number
    {
        let maxY:number = 0;

        for (let x = 0; x <= GameManager.Instance.col - 1; x++)
        {
            for (let y = 0; y <= GameManager.Instance.row - 1; y++)
            {
                let cell:Cell = GameManager.Instance.cellList[x][y];
                if (cell != null && cell.isNew == false && cell.y > maxY && cell.y <= GameManager.Instance.row - 1)
                {
                    maxY = y;
                }
            }
        }

        return maxY;
    }

    // 获取位置
    public static GetPosition(_x:number, _y:number):cc.Vec2
    {
        let pos:cc.Vec2 = null;

        var pos_x = GameManager.Instance.cellSize * _x - GameManager.Instance.width / 2  + GameManager.Instance.cellSize / 2;
        var pos_y = GameManager.Instance.cellSize * _y - GameManager.Instance.height_screen / 2 + GameManager.Instance.cellSize / 2 + GameManager.Instance.padding_bottom;
        pos = new cc.Vec2(pos_x, pos_y);

        return pos;
    }

    //9宫格爆炸
    public static Explore9(_x:number, _y:number)
    {
        if (GameManager.Instance.cellList == null || GameManager.Instance.cellList.length == 0)
        {
            return;
        }

        for (let x = _x - 1; x <= _x + 1; x++)
        {
            for (let y = _y - 1; y <= _y + 1; y++)
            {
                let cell:Cell = CellFunctions.GetCell(x, y);
                if (cell != null)
                {
                    cell.Dead();
                }
            }
        }

        AudioManager.Instance.audio_explore.play();
        // AudioManager.Instance.Play(AudioManager.Instance.audio_explore);
    }


    //延时函数
    public static DelayFunction(_callback:Function, _complete:Function, _loop:number = 1, _duration:number = 1)
    {
        if(_callback)
        {
            _callback();
        }

        if(_loop <= 1)
        {
            if(_complete)
            {
                _complete();
            }
            return;
        }
        
        let count = 1;
        let callback = function () 
        {
            if(_callback)
            {
                _callback();
            }

            if (count >= _loop - 1) 
            {
                GameManager.Instance.unschedule(callback);

                if(_complete)
                {
                    _complete();
                }
            }

            count++;
        }
        GameManager.Instance.schedule(callback, _duration);
    }

}
